package com.ruoyi.thread;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easemob.im.server.model.EMUser;
import com.ruoyi.common.aliyun.AliPaymentConfig;
import com.ruoyi.common.baidu.AuthService;
import com.ruoyi.common.core.redis.RedisUtil;
import com.ruoyi.common.huanxing.EMServiceUtil;
import com.ruoyi.common.push.UniBatchPushUtil;
import com.ruoyi.common.push.UnipushUtil;
import com.ruoyi.common.utils.CommonUtil;
import com.ruoyi.common.utils.HmacSha;
import com.ruoyi.common.utils.OrderNumberGeneratorUtil;
import com.ruoyi.common.utils.ProjectConstant;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.date.DateUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.oss.OSSStsUtil;
import com.ruoyi.common.utils.parameter.SystemPushText;
import com.ruoyi.dynamic.domain.UserDynamic;
import com.ruoyi.dynamic.mapper.UserDynamicMapper;
import com.ruoyi.order.domain.OrderInfo;
import com.ruoyi.order.domain.OrderTask;
import com.ruoyi.order.domain.UserAppleRefund;
import com.ruoyi.order.mapper.OrderInfoMapper;
import com.ruoyi.order.mapper.OrderTaskMapper;
import com.ruoyi.order.mapper.UserAppleRefundMapper;
import com.ruoyi.problem.mapper.ProblemAnswerMapper;
import com.ruoyi.problem.mapper.ProblemConsultMapper;
import com.ruoyi.problem.pojo.AnswerDTO;
import com.ruoyi.problem.pojo.OrderGrabbingPoolDTO;
import com.ruoyi.system.domain.PriceSetting;
import com.ruoyi.system.domain.RegularMsgSend;
import com.ruoyi.system.domain.SystemDivine;
import com.ruoyi.system.domain.UserSystemMsg;
import com.ruoyi.system.mapper.PriceSettingMapper;
import com.ruoyi.system.mapper.RegularMsgSendMapper;
import com.ruoyi.system.mapper.SystemDivineMapper;
import com.ruoyi.system.service.IUserSystemMsgService;
import com.ruoyi.user.domain.FileAttachment;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.domain.UserCapitalFlow;
import com.ruoyi.user.domain.UserExtend;
import com.ruoyi.user.domain.UserProject;
import com.ruoyi.user.domain.UserTotalCapital;
import com.ruoyi.user.domain.UserViewRecord;
import com.ruoyi.user.domain.UserVoiceCall;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.mapper.UserProjectMapper;
import com.ruoyi.user.mapper.UserViewRecordMapper;
import com.ruoyi.user.mapper.UserVoiceCallMapper;
import com.ruoyi.user.pojo.AppUserDetail;
import com.ruoyi.user.service.IFileAttachmentService;
import com.ruoyi.user.service.IUserCapitalFlowService;
import com.ruoyi.user.service.IUserExtendService;
import com.ruoyi.user.service.IUserTotalCapitalService;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;

/**
 *	异步处理任务
 * @author DEREK
 */
@Component
public class TaskAsync {


	@Autowired
	private UserMapper userMapper;
	@Autowired
	private UserViewRecordMapper userViewRecordMapper;
	@Autowired
	private IUserExtendService userExtendService;
	@Autowired
	private EMServiceUtil eMServiceUtil;
	@Autowired
	private IFileAttachmentService fileAttachmentService;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private IUserSystemMsgService userSystemMsgService;
	@Autowired
	private UserDynamicMapper userDynamicMapper;
	@Autowired
	private OrderTaskMapper orderTaskMapper;
	@Autowired
	private ProblemConsultMapper problemConsultMapper;
	@Autowired
	private SystemDivineMapper systemDivineMapper;
	@Autowired
	private ProblemAnswerMapper problemAnswerMapper;
	@Autowired
	private UserVoiceCallMapper userVoiceCallMapper;
	@Autowired
	private IUserTotalCapitalService userTotalCapitalService;
	@Autowired
	private IUserCapitalFlowService userCapitalFlowService;
	@Autowired
	private OrderInfoMapper orderInfoMapper;
	@Autowired
	private AliPaymentConfig aliPaymentConfig;
	@Autowired
	private PriceSettingMapper priceSettingMapper;
	@Autowired
	private RegularMsgSendMapper regularMsgSendMapper;
	@Autowired
	private UserAppleRefundMapper userAppleRefundMapper;
	
	public static BigDecimal test(OrderInfo info) {
		info.setOrderAmount(BigDecimal.ONE);
		return BigDecimal.ONE;
	}
	
	
	@Async("asyncServiceExecutor")
	public void appleRefund(Long id) {
		UserAppleRefund refund = userAppleRefundMapper.selectById(id);
		if(null == refund) {
			return;
		}
		OrderInfo order = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>()
				.eq(OrderInfo::getTradeNo, refund.getTransactionId())
				.last("limit 1"));
		if(null == order) {
			return;
		}
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
				.eq(User::getId, order.getPayUserId()));
		if(null == user) {
			refund.setUserId(0L);
			refund.setNickName("用户不存在");
		}else {
			refund.setUserId(user.getId());
			refund.setNickName(user.getNickName());
		}
		userAppleRefundMapper.updateById(refund);
		if("REFUND".equalsIgnoreCase(refund.getNotificationType())) {
			if("1".equals(order.getOrderType())) { // 充值VIP
				PriceSetting set = priceSettingMapper.selectById(order.getRelatedId());
				if(null != set) {
					user.setVipExpireTime(DateUtils.addDateForMonths(user.getVipExpireTime(), -Integer.valueOf(set.getPayCode())));
					if(!DateUtils.isOverdue(new Date(), user.getVipExpireTime())) {
						user.setVip(0);
						user.setVipLevel(0);
					}
					userMapper.updateById(user);
				}
				order.setOrderStatus("3");
				orderInfoMapper.updateById(order);
			}else if("6".equals(order.getOrderType())) { // 充值金币
				userTotalCapitalService.initUserTotalCapital("3", user.getId(), order.getOrderAmount(), 0);
				order.setOrderStatus("3");
				orderInfoMapper.updateById(order);
			}
		}
	}
	
	/**
	 * 	更新用户详细地址
	 * @param user
	 * @param longitude
	 * @param latitude
	 */
	@Async("asyncServiceExecutor")
	public void updUserDetailedAddress(Long userId,BigDecimal longitude,BigDecimal latitude) {
		longitude = longitude.setScale(6, BigDecimal.ROUND_DOWN);
		latitude = latitude.setScale(6, BigDecimal.ROUND_DOWN);
		String detailedAddress = HttpUtils.getDetailedAddress(longitude, latitude);
		if(!"fail".equals(detailedAddress)) {
			User user = new User();
			user.setId(userId);
			user.setDetailAddress(detailedAddress);
			userMapper.updateById(user);
		}
	}
	
	
	public static void main(String[] args) {
//		BigDecimal number = new BigDecimal("123.456789999999");
//		BigDecimal result = number.setScale(6, BigDecimal.ROUND_DOWN);
//		System.out.println(result);
		 String[] li = {"中国","美国","英国","法国","德国","俄罗斯"};
		    Random random = new Random();
		    for (int j = 0; j < 50; j++) {
//		        String country = li[random.nextInt(li.length)];
//		        System.out.println("country = " + country);
		    	System.out.println(random.nextInt(li.length));
		    }
		
	}
	
	
	/**
	 * 	添加发送消息定时任务
	 * @param userId
	 * @param date
	 */
	@Async("asyncServiceExecutor")
	public void joinMsgSendCron(Long userId,Date date,String sex) {
		List<RegularMsgSend> list = regularMsgSendMapper.selectList(new LambdaQueryWrapper<RegularMsgSend>().eq(RegularMsgSend::getIsEnabled, 1));
		if(CollectionUtil.isEmpty(list)) {
			return;
		}
		for (RegularMsgSend reg : list) {
			Date newDate = date;
			if(reg.getTimeDay() > 0) {
				newDate = DateUtils.addDateForDays(newDate, reg.getTimeDay());
			}
			if(reg.getTimeHour() > 0) {
				newDate = DateUtils.addHour(newDate, reg.getTimeHour());
			}
			if(reg.getTimeMinute() > 0) {
				newDate = DateUtils.addMinute(newDate, reg.getTimeMinute());
			}
			if(reg.getTimeSecond() > 0) {
				newDate = DateUtils.addSecondDate(newDate, reg.getTimeSecond());
			}
			if("F".equalsIgnoreCase(sex) && "M".equalsIgnoreCase(reg.getSex())) {
				OrderTask task = new OrderTask();
				task.setRelatedId(String.valueOf(reg.getId()));
				task.setUserId(reg.getUserId());
				task.setToUserId(userId);
				task.setType(7);
				task.setRemark("新用户自动发送消息-男性发给女性");
				task.setExtend(reg.getContent());
				task.setEndTime(newDate);
				if(reg.getContent().contains("#")) {
					Random random = new Random();
					String[] split = reg.getContent().split("#");
					String ext = split[random.nextInt(split.length)];
					task.setExtend(ext);
				}
				orderTaskMapper.insert(task);
			}else if("M".equalsIgnoreCase(sex) && "F".equalsIgnoreCase(reg.getSex())){
				OrderTask task = new OrderTask();
				task.setRelatedId(String.valueOf(reg.getId()));
				task.setUserId(reg.getUserId());
				task.setToUserId(userId);
				task.setType(7);
				task.setRemark("新用户自动发送消息-女性发给男性");
				task.setExtend(reg.getContent());
				task.setEndTime(newDate);
				if(reg.getContent().contains("#")) {
					Random random = new Random();
					String[] split = reg.getContent().split("#");
					String ext = split[random.nextInt(split.length)];
					task.setExtend(ext);
				}
				orderTaskMapper.insert(task);
			}
		}
	}
	
	@Autowired
	private UserProjectMapper userProjectMapper;
	/**
	 * 	新用户注册推送消息
	 * @param userId		发送者 
	 * @param toUserId		接收者
	 * @param content		消息内容
	 */
	@Async("asyncServiceExecutor")
	public void newUserRegisterSendMsg(Long userId,Long toUserId,String content) {
		AppUserDetail form = new AppUserDetail();
    	form.setType(1);
    	form.setUserId(userId);
    	List<AppUserDetail> userBasicInfo = userMapper.getUserBasicInfo(form);
    	if(CollectionUtil.isEmpty(userBasicInfo)) {
    		return;
    	}
    	form = userBasicInfo.get(0);
    	AppUserDetail toU = new AppUserDetail();
    	toU.setType(1);
    	toU.setUserId(toUserId);
    	List<AppUserDetail> toUserBasicInfo = userMapper.getUserBasicInfo(toU);
    	if(CollectionUtil.isEmpty(toUserBasicInfo)) {
    		return;
    	}
    	toU = toUserBasicInfo.get(0);
    	Map<String,Object> map = new HashMap<String,Object>();
		map.put("myHeadPic", form.getHeadPic());
		map.put("myName", form.getEmUsername());
		map.put("myName_custom", form.getNickName());
		map.put("userId_my", form.getUserId());
		map.put("userId_your", toU.getUserId());
		map.put("your", toU.getEmUsername());
		map.put("yourHeadPic", toU.getHeadPic());
		map.put("your_custom", toU.getNickName());
		Set<String> setIds = new HashSet<String>();
		setIds.add(toU.getEmUsername());
    	eMServiceUtil.sendSystemMsg(form.getEmUsername(), content, setIds, map);
    	UserProject project = new  UserProject();
    	project.setUserId(toUserId);
    	project.setTitle(String.valueOf(userId));
    	project.setRemark(JSONObject.toJSONString(map));
    	userProjectMapper.insert(project);
    	
	}
	
	/**
	 * 	添加账单流水
	 * @param userId			用户ID
	 * @param toUserId			对方ID
	 * @param type				业务类型1：充值VIP 2：提现 3：充值花蜜 4：礼物 5：解锁微信 6：解锁聊天
	 * @param amount			金额
	 * @param sourceType		来源 1=微信 2-支付宝 3=余额 4=苹果 
	 * @param isCommission		是否对方抽佣 0=否 1=是
	 */
	@Async("asyncServiceExecutor")
	public void addUserCapitalFlow(Long userId,Long toUserId,Integer type,BigDecimal amount,Integer sourceType,Integer isCommission) {
		List<UserCapitalFlow> list = new ArrayList<UserCapitalFlow>();
		switch (type) {
		case 1:
			UserCapitalFlow cuFlow = new UserCapitalFlow();
			cuFlow.setType(2);
			cuFlow.setBusinessType(1);
			cuFlow.setAmount(amount);
			cuFlow.setUserId(userId);
			cuFlow.setToUserId(toUserId);
			cuFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			cuFlow.setRemark("充值VIP,消费记录");
			cuFlow.setSource(sourceType);
			list.add(cuFlow);
			// 充值VIP 给对方分佣
			if(null != toUserId && toUserId > 0) {
				userTotalCapitalService.initUserTotalCapital("1", toUserId,amount.multiply(new BigDecimal("0.5")),1);
			}
			break;
		case 2:
			
			break;
		case 3:
			cuFlow = new UserCapitalFlow();
			cuFlow.setType(2);
			cuFlow.setBusinessType(3);
			cuFlow.setAmount(amount);
			cuFlow.setUserId(userId);
			cuFlow.setToUserId(toUserId);
			cuFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			cuFlow.setRemark("充值花蜜,消费记录");
			cuFlow.setSource(sourceType);
			list.add(cuFlow);
			break;
		case 4:
			
			
			break;
		case 5:
			cuFlow = new UserCapitalFlow();
			cuFlow.setType(5);
			cuFlow.setBusinessType(5);
			cuFlow.setAmount(amount);
			cuFlow.setUserId(userId);
			cuFlow.setToUserId(toUserId);
			cuFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			cuFlow.setRemark("用户解锁微信,消费记录");
			cuFlow.setSource(sourceType);
			list.add(cuFlow);
			if(1 == isCommission) {
				PriceSetting price = priceSettingMapper.selectOne(new LambdaQueryWrapper<PriceSetting>().eq(PriceSetting::getPriceType, "unlock_commission")
						.select(PriceSetting::getId,PriceSetting::getCurrentPrice));
				if(null != price && null != price.getCurrentPrice() && price.getCurrentPrice().compareTo(BigDecimal.ZERO) == 1) {
					amount = amount.multiply(price.getCurrentPrice());
				}
				UserCapitalFlow toFlow = new UserCapitalFlow();
				toFlow.setType(4);
				toFlow.setBusinessType(5);
				toFlow.setAmount(amount);
				toFlow.setUserId(toUserId);
				toFlow.setToUserId(userId);
				toFlow.setOrderNo(OrderNumberGeneratorUtil.get());
				toFlow.setRemark("被用户解锁微信,收益记录");
				toFlow.setSource(sourceType);
				list.add(toFlow);
			}
			break;
		case 6:
			cuFlow = new UserCapitalFlow();
			cuFlow.setType(5);
			cuFlow.setBusinessType(6);
			cuFlow.setAmount(amount);
			cuFlow.setUserId(userId);
			cuFlow.setToUserId(toUserId);
			cuFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			cuFlow.setRemark("用户解锁聊天,消费记录");
			cuFlow.setSource(sourceType);
			list.add(cuFlow);
			if(1 == isCommission) {
				PriceSetting price = priceSettingMapper.selectOne(new LambdaQueryWrapper<PriceSetting>().eq(PriceSetting::getPriceType, "unlock_commission")
						.select(PriceSetting::getId,PriceSetting::getCurrentPrice));
				if(null != price && null != price.getCurrentPrice() && price.getCurrentPrice().compareTo(BigDecimal.ZERO) == 1) {
					amount = amount.multiply(price.getCurrentPrice());
				}
				UserCapitalFlow toFlow = new UserCapitalFlow();
				toFlow.setType(4);
				toFlow.setBusinessType(6);
				toFlow.setAmount(amount);
				toFlow.setUserId(toUserId);
				toFlow.setToUserId(userId);
				toFlow.setOrderNo(OrderNumberGeneratorUtil.get());
				toFlow.setRemark("被用户解锁聊天,收益记录");
				toFlow.setSource(sourceType);
				list.add(toFlow);
			}
			break;
		default:
			break;
		}
		userCapitalFlowService.saveBatch(list);
	}
	
	/**
	 * 	处理后台删除咨询问题，金额原路退回 ， 删除定时任务
	 * @param cid
	 */
	@Async("asyncServiceExecutor")
	public void handleConsultDel(Long cid,Long userId) {
		// 查询订单
		OrderInfo order = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getRelatedId, cid).eq(OrderInfo::getOrderType, 3)
				.eq(OrderInfo::getOrderStatus, 1).eq(OrderInfo::getPayUserId, userId));
		UserCapitalFlow cap = new UserCapitalFlow();
		cap.setType(6);
		cap.setBusinessType(11);
		cap.setUserId(userId);
		cap.setToUserId(4l);
		cap.setIsSettle(0);
		cap.setRemark("打赏咨询,后台管理员删除提问,金额原路退还");
		cap.setRelatedId(cid);
		if(null == order) {
			cap.setRemark(cap.getRemark()+"-订单不存在退款失败！");
			userCapitalFlowService.save(cap);
			return;
		}
		cap.setAmount(order.getOrderAmount());
		cap.setOrderNo(order.getOrderNo());
		if("3".equals(order.getPayType())) {
			cap.setSource(0);
		}else {
			cap.setSource(Integer.valueOf(order.getPayType()));
		}
		// 删除定时任务
		orderTaskMapper.delete(new LambdaQueryWrapper<OrderTask>().eq(OrderTask::getExtend, cid));
		// 退金额
		if("1".equals(order.getPayType())) {	// 微信 
			
			
		}else if("2".equals(order.getPayType())) {	// 支付宝 
			String retStr = aliPaymentConfig.aliPayOriginalRefund(order.getTradeNo(), order.getOrderAmount(), "打赏退款");
			if(!"SUCCESS".equals(retStr)) {
				cap.setRemark(cap.getRemark()+"-退款失败！");
				cap.setNameType(retStr);
				userCapitalFlowService.save(cap);
			}
			
		}else if("3".equals(order.getPayType())) {	// 余额
			userTotalCapitalService.initUserTotalCapital("3", userId, order.getOrderAmount(), 1);
		}
		cap.setIsSettle(1);
		cap.setRemark(cap.getRemark()+"-退款成功！");
		userCapitalFlowService.save(cap);
	}
	
	/**
	 * 	采纳咨询师回答发送消息
	 * @param userId			提问者id
	 * @param toUserId			回答者id
	 * @param type				1=正常采纳 2=24h自动采纳
	 */
	@Async("asyncServiceExecutor")
	public void addProblemAnswerMsg(Long userId,Long toUserId,Integer type) {
		if(null == userId || null == toUserId) {
			return;
		}
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getNickName));
		if(null == user) {
			return;
		}
		User toUser = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, toUserId).select(User::getId,User::getNickName));
		if(null == toUser) {
			return;
		}
		String title = "采纳咨询师回复";
		List<UserSystemMsg> msgList = new ArrayList<UserSystemMsg>();
		if(1 == type) {
			UserSystemMsg userMsg = new UserSystemMsg();
			userMsg.setUserId(userId);
			userMsg.setToUserId(0L);
			userMsg.setTitle(title);
			userMsg.setContent("采纳咨询师回复成功,可继续跟咨询师(昵称:"+toUser.getNickName()+")私聊获得解答~");
			userMsg.setType(2);
			msgList.add(userMsg);
			userMsg = new UserSystemMsg();
			userMsg.setUserId(toUserId);
			userMsg.setToUserId(0L);
			userMsg.setTitle(title);
			userMsg.setContent("用户(昵称:"+user.getNickName()+"),采纳了您的回复请尽快与他联系~");
			userMsg.setType(2);
			msgList.add(userMsg);
		}else if(2 == type){
			UserSystemMsg userMsg = new UserSystemMsg();
			userMsg.setUserId(userId);
			userMsg.setToUserId(0L);
			userMsg.setTitle(title);
			userMsg.setContent("24h自动采纳咨询师回复成功,可继续跟咨询师(昵称:"+toUser.getNickName()+")私聊获得解答~");
			userMsg.setType(2);
			msgList.add(userMsg);
			userMsg = new UserSystemMsg();
			userMsg.setUserId(toUserId);
			userMsg.setToUserId(0L);
			userMsg.setTitle(title);
			userMsg.setContent("24h自动采纳咨询师回复成功,用户(昵称:"+user.getNickName()+"),采纳了您的回复请尽快与他联系~");
			userMsg.setType(2);
			msgList.add(userMsg);
		}else {
			return;
		}
		userSystemMsgService.saveBatch(msgList);
		
	}
	
	/**
	 * 	抢单池--24h后自动采纳第一个回答问题的咨询师
	 * @param userId			提问者id
	 * @param toUserId			回答者id
	 * @param cid			问题ID
	 * @param pid			回答ID
	 */
	@Async("asyncServiceExecutor")
	public void addProblemAnswerTask(Long userId,Long toUserId,BigDecimal amount,Long pid,Long cid) {
		OrderTask task = new OrderTask();
		task.setRelatedId(String.valueOf(pid));
		task.setUserId(userId);
		task.setToUserId(toUserId);
		task.setOrderNo(String.valueOf(amount));
		task.setEndTime(DateUtils.addDateForDays(new Date(), 1));
		task.setType(4);
		task.setRemark("24h自动采纳第一条回复");
		task.setExtend(String.valueOf(cid));
		orderTaskMapper.insert(task);
	}
	
	/**
	 * 	推送下单订单消息
	 * @param userId		接收者用户ID
	 * @param toUserId		咨询师用户ID
	 * @param prTitle		项目标题
	 * @param sendType		2=活动支付 4=单次咨询支付
	 * @param amount		金额
	 * @param payType		0=钻石 1=微信 2-支付宝 4=苹果
	 */
	@Async("asyncServiceExecutor")
	public void addOrderMsg(Long userId,Long toUserId,Integer sendType,String prTitle,BigDecimal amount,BigDecimal toAmount,Integer payType) {
		if(null == userId || null == toUserId) {
			return;
		}
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getNickName));
		if(null == user) {
			return;
		}
		User toUser = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, toUserId).select(User::getId,User::getNickName));
		if(null == toUser) {
			return;
		}
		
//		List<UserSystemMsg> msgList = new ArrayList<UserSystemMsg>();
		List<UserCapitalFlow> flowList = new ArrayList<UserCapitalFlow>();
		if(2 == sendType) {
//			UserSystemMsg userMsg = new UserSystemMsg();
//			userMsg.setUserId(userId);
//			userMsg.setToUserId(0L);
//			userMsg.setTitle("活动报名成功");
//			userMsg.setContent("活动报名成功(活动名称:"+prTitle+"),请尽快与咨询师(昵称:"+toUser.getNickName()+")联系~");
//			userMsg.setType(2);
//			msgList.add(userMsg);
//			userMsg = new UserSystemMsg();
//			userMsg.setUserId(toUserId);
//			userMsg.setToUserId(0L);
//			userMsg.setTitle("活动报名成功");
//			userMsg.setContent("用户(昵称:"+user.getNickName()+")报名了您的活动(活动名称:"+prTitle+"),请尽快与他联系~");
//			userMsg.setType(2);
//			msgList.add(userMsg);
			// 添加流水
			UserCapitalFlow userCapitalFlow = new UserCapitalFlow();
			userCapitalFlow.setType(5);
			userCapitalFlow.setBusinessType(9);
			userCapitalFlow.setAmount(amount);
			userCapitalFlow.setUserId(userId);
			userCapitalFlow.setToUserId(toUserId);
			userCapitalFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			userCapitalFlow.setRemark("报名活动支出");
			userCapitalFlow.setSource(payType);
			flowList.add(userCapitalFlow);
			userCapitalFlow = new UserCapitalFlow();
			userCapitalFlow.setType(4);
			userCapitalFlow.setBusinessType(9);
			userCapitalFlow.setAmount(toAmount);
			userCapitalFlow.setUserId(toUserId);
			userCapitalFlow.setToUserId(userId);
			userCapitalFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			userCapitalFlow.setRemark("报名活动收入");
			userCapitalFlow.setSource(payType);
			flowList.add(userCapitalFlow);
		}else if(4 == sendType){ // 单次咨询支付
//			UserSystemMsg userMsg = new UserSystemMsg();
//			userMsg.setUserId(userId);
//			userMsg.setToUserId(0L);
//			userMsg.setTitle("单次咨询支付成功");
//			userMsg.setContent("单次咨询支付成功(项目名称:"+prTitle+"),请尽快与咨询师(昵称:"+toUser.getNickName()+")联系~");
//			userMsg.setType(2);
//			msgList.add(userMsg);
//			userMsg = new UserSystemMsg();
//			userMsg.setUserId(toUserId);
//			userMsg.setToUserId(0L);
//			userMsg.setTitle("单次咨询支付成功");
//			userMsg.setContent("用户(昵称:"+user.getNickName()+")下单了您的单项问题咨询(项目名称:"+prTitle+"),请尽快接单并于用户联系~");
//			userMsg.setType(2);
//			msgList.add(userMsg);
			// 添加流水
			UserCapitalFlow userCapitalFlow = new UserCapitalFlow();
			userCapitalFlow.setType(5);
			userCapitalFlow.setBusinessType(10);
			userCapitalFlow.setAmount(amount);
			userCapitalFlow.setUserId(userId);
			userCapitalFlow.setToUserId(toUserId);
			userCapitalFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			userCapitalFlow.setRemark("单次咨询支出");
			userCapitalFlow.setSource(payType);
			flowList.add(userCapitalFlow);
			userCapitalFlow = new UserCapitalFlow();
			userCapitalFlow.setType(4);
			userCapitalFlow.setBusinessType(10);
			userCapitalFlow.setAmount(toAmount);
			userCapitalFlow.setUserId(toUserId);
			userCapitalFlow.setToUserId(userId);
			userCapitalFlow.setOrderNo(OrderNumberGeneratorUtil.get());
			userCapitalFlow.setRemark("单次咨询收入");
			userCapitalFlow.setSource(payType);
			flowList.add(userCapitalFlow);
		}else {
			return;
		}
//		userSystemMsgService.saveBatch(msgList);
		userCapitalFlowService.saveBatch(flowList);
	}
	

	/**
	 * 	主动销毁房间
	 * @param roomId	房间ID
	 */
	@Async("asyncServiceExecutor")
	public boolean destructionRoom(String roomId) {
		boolean flag = false;
		String nonce = OrderNumberGeneratorUtil.get();
		String timestamp = System.currentTimeMillis()+"";
		try {
			String signature = HmacSha.shaEncode(ProjectConstant.RONG_CLOUD_APP_SECRET+nonce+timestamp);
			String result = HttpUtils.deleteUrlencodedRongCloud(ProjectConstant.RONG_CLOUD_DELETE_ROOM+roomId, nonce, timestamp, signature);
			JSONObject resultObj = JSONObject.parseObject(result);
			if(10000 == resultObj.getInteger("code")) {
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * 	计算余额能够拨打多长时间的语音通话
	 * @param userId
	 */
	@Async("asyncServiceExecutor")
	public void computeAmount(Long id,Long userId,String roomId,Long toUserId) {
		UserTotalCapital total = userTotalCapitalService.getOne(new LambdaQueryWrapper<UserTotalCapital>().eq(UserTotalCapital::getUserId, userId)
				.eq(UserTotalCapital::getAmountType, 3));
		if(null == total || total.getTotalAmount().compareTo(BigDecimal.ZERO) <= 0) {
			destructionRoom(roomId);
			userSystemMsgService.pushSystemMsg(userId, "余额不足自动挂断", "您的可用余额不足,系统已自动挂断！");
			return;
		}
		// 计算每分钟金额
		BigDecimal minAmount = new BigDecimal("3");
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, toUserId).select(User::getId,User::getPrice));
		if(null != user && null != user.getPrice()) {
			minAmount = user.getPrice();
		}
		BigDecimal divide = total.getTotalAmount().divide(minAmount);
		int minute = divide.intValue();
		if(minute <= 5) {
			destructionRoom(roomId);
			userSystemMsgService.pushSystemMsg(userId, "余额不足自动挂断", "您的可用余额不足通话5分钟以上,系统已自动挂断！");
			return;
		}
		
//		BigDecimal amount = new BigDecimal("5");
//		PriceSetting set = priceSettingMapper.selectOne(new LambdaQueryWrapper<PriceSetting>().eq(PriceSetting::getPriceType, "语音通话"));
//		if(null != set && null != set.getCurrentPrice()) {
//			amount = set.getCurrentPrice();
//		}
//		BigDecimal divide = total.getTotalAmount().divide(amount);
//		int minute = divide.intValue();
//		if(minute <= 5) {
//			destructionRoom(roomId);
//			userSystemMsgService.pushSystemMsg(userId, "余额不足自动挂断", "您的可用余额不足通话5分钟以上,系统已自动挂断！");
//			return;
//		}
		OrderTask task = new OrderTask();
		task.setRelatedId(String.valueOf(id));
		task.setOrderNo(roomId);
		task.setUserId(userId);
		task.setType(2);
		task.setRemark("语音通话低于5分钟提醒用户充值");
		task.setEndTime(DateUtils.addMinute(new Date(), (minute-5)));
		orderTaskMapper.insert(task);
		
		OrderTask taskEnd = new OrderTask();
		taskEnd.setRelatedId(String.valueOf(id));
		taskEnd.setOrderNo(roomId);
		taskEnd.setUserId(userId);
		taskEnd.setType(3);
		taskEnd.setRemark("语音通话余额不足自动挂断");
		taskEnd.setEndTime(DateUtils.addMinute(new Date(), minute));
		orderTaskMapper.insert(taskEnd);
	}

	/**
	 * 	语音通话结算
	 * @param voice
	 */
	@Async("asyncServiceExecutor")
	@Transactional
	public void settlementVoiceCall(UserVoiceCall voice) {
		// 删除定时提醒任务
		List<OrderTask> taskList = orderTaskMapper.selectList(new LambdaQueryWrapper<OrderTask>().eq(OrderTask::getOrderNo, voice.getRoomId()).eq(OrderTask::getStatus, 0));
		if(CollectionUtils.isNotEmpty(taskList)) {
			taskList.stream().forEach(task ->{
				task.setRemark(task.getRemark()+"-挂断正常结束");
				task.setStatus(2);
				orderTaskMapper.updateById(task);
			});
		}
		if(1 == voice.getIsSettle()) {
			return;
		}
		UserTotalCapital total = userTotalCapitalService.getOne(new LambdaQueryWrapper<UserTotalCapital>().eq(UserTotalCapital::getUserId, voice.getUserId())
				.eq(UserTotalCapital::getAmountType, 3));
		if(null == total || total.getTotalAmount().compareTo(BigDecimal.ZERO) <= 0) {
			return;
		}
		// 计算每分钟金额
		BigDecimal amount = new BigDecimal("3");
//		PriceSetting set = priceSettingMapper.selectOne(new LambdaQueryWrapper<PriceSetting>().eq(PriceSetting::getPriceType, "voiceCoallPrice"));
//		if(null != set && null != set.getCurrentPrice()) {
//			amount = set.getCurrentPrice();
//		}
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, voice.getToUserId()).select(User::getId,User::getPrice));
		if(null != user && null != user.getPrice() && user.getPrice().compareTo(BigDecimal.ZERO) == 1) {
			amount = user.getPrice();
		}
		BigDecimal minute = BigDecimal.ONE;
		long minutes = 0l;
		if(StringUtils.isNotEmpty(voice.getExtend())) {
			minutes = TimeUnit.MILLISECONDS.toMinutes(Long.valueOf(voice.getExtend()));
			if(minutes > 0) {
				minute = new BigDecimal(minutes);
			}
		}else {
			if(null == voice.getBegTime() || null == voice.getEndTime()) {
				return;
			}
			minutes = TimeUnit.MILLISECONDS.toMinutes((voice.getEndTime().getTime()-voice.getBegTime().getTime()));
			if(minutes <= 0) {
				return;
			}
			minute = new BigDecimal(minutes);
		}
		BigDecimal totalAmount = amount.multiply(minute);
		if(total.getTotalAmount().compareTo(totalAmount) <= 0) {
			totalAmount = total.getTotalAmount();
		}
		// 扣除金额 增加收益
		total.setTotalAmount(total.getTotalAmount().subtract(totalAmount));
		userTotalCapitalService.updateById(total);
		userTotalCapitalService.initUserTotalCapital("1", voice.getToUserId(), totalAmount, 1);
		// 改成已结算
		voice.setIsSettle(1);
		voice.setAmount(totalAmount);
		voice.setMinute(minutes);
		userVoiceCallMapper.updateById(voice);
		// 添加流水 
		UserCapitalFlow userFlow = new UserCapitalFlow();
		userFlow.setType(5);
		userFlow.setBusinessType(7);
		userFlow.setAmount(totalAmount);
		userFlow.setUserId(voice.getUserId());
		userFlow.setToUserId(voice.getToUserId());
		userFlow.setOrderNo(voice.getRoomId());
		userFlow.setRemark("支付语音通话费用");
		userFlow.setRelatedId(voice.getId());

		UserCapitalFlow toUserFlow = new UserCapitalFlow();
		toUserFlow.setType(4);
		toUserFlow.setBusinessType(8);
		toUserFlow.setAmount(totalAmount);
		toUserFlow.setUserId(voice.getToUserId());
		toUserFlow.setToUserId(voice.getUserId());
		toUserFlow.setOrderNo(voice.getRoomId());
		toUserFlow.setRemark("收益语音通话费用");
		toUserFlow.setRelatedId(voice.getId());
		List<UserCapitalFlow> list = new ArrayList<UserCapitalFlow>();
		list.add(userFlow);
		list.add(toUserFlow);
		userCapitalFlowService.saveBatch(list);
	}


	/**
	 * 	发送占卜接口采纳消息
	 * @param userId
	 * @param toUserId
	 */
	@Async("asyncServiceExecutor")
	public void sendDivineOrderMsg(Long loginUserId,Long toUserId,Long id,Long answerId) {
		UserExtend curr = userExtendService.getOne(new LambdaQueryWrapper<UserExtend>().eq(UserExtend::getUserId, loginUserId).select(UserExtend::getId,UserExtend::getEmUsername));
		UserExtend to = userExtendService.getOne(new LambdaQueryWrapper<UserExtend>().eq(UserExtend::getUserId, toUserId).select(UserExtend::getId,UserExtend::getEmUsername));
		if((null != curr && StringUtils.isNotEmpty(curr.getEmUsername())) && (null != to && StringUtils.isNotEmpty(to.getEmUsername()))) {
			Map<String,Object> map = new HashMap<String, Object>();
			// 组装自定义消息内容
			IPage<OrderGrabbingPoolDTO> list = problemConsultMapper.getOrderGrabbingPool(new Page<OrderGrabbingPoolDTO>().setCurrent(0).setSize(10),id,null);
			if(CollectionUtil.isEmpty(list.getRecords())) {
				return;
			}
			OrderGrabbingPoolDTO orderGrabbingPool = list.getRecords().get(0);
			// 占卜结果
			List<SystemDivine> divineList = systemDivineMapper.selectList(new LambdaQueryWrapper<SystemDivine>().in(SystemDivine::getId, orderGrabbingPool.getDid()));
			if(CollectionUtil.isNotEmpty(divineList)) {
				orderGrabbingPool.setDivineList(divineList);
			}
			// 解答列表
			List<AnswerDTO> answerList = problemAnswerMapper.getAnswerList(orderGrabbingPool.getId(),answerId);
			if(CollectionUtil.isNotEmpty(answerList)) {
				answerList.stream().forEach(answer ->{
					if(null != answer.getBirthday()) {
						//处理年龄
						if(answer.getBirthday() != null) {
							answer.setAge(CommonUtil.getAge(answer.getBirthday()));
						}else {
							answer.setAge(22);
						}
						// 处理语音
						if(loginUserId.longValue() != orderGrabbingPool.getUserId().longValue() || loginUserId.longValue() != answer.getUserId().longValue()) {
							answer.setVoice("");
						}
					}
				});
				orderGrabbingPool.setAnswerList(answerList);
			}
			map.put("record", orderGrabbingPool);
			eMServiceUtil.sendCustomMsg(curr.getEmUsername(), to.getEmUsername(), "divineOrder", map);
		}
	}

	/**
	 * 	更新用户在线状态
	 * @param userId
	 */
	@Async("asyncServiceExecutor")
	public void updateUserStatus(Long userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getVip,User::getVipExpireTime));
		if(null == user) {
			return;
		}
		user.setLoginTime(new Date());
		if(null == user.getVipExpireTime() || !DateUtils.isOverdue(new Date(), user.getVipExpireTime())) {
			user.setVip(0);
			//VIP已过期 将已经开通的权益消失
			user.setIsStealth(0);
			user.setHideView(0);
//			user.setMessageCount(0);
		}else {
			user.setVip(1);
		}
		userMapper.updateById(user);
	}
	
	
	@Async("asyncServiceExecutor")
	public void updateUserVip(Long userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getVip,User::getVipExpireTime));
		if(null == user) {
			return;
		}
		if(null == user.getVipExpireTime() || !DateUtils.isOverdue(new Date(), user.getVipExpireTime())) {
			user.setVip(0);
			//VIP已过期 将已经开通的权益消失
			user.setIsStealth(0);
			user.setHideView(0);
//			user.setMessageCount(0);
		}else {
			user.setVip(1);
		}
		userMapper.updateById(user);
	}
	

	/**
	 * 	添加订单到规定时间未支付业务
	 * @param businessId
	 * @param orderNo
	 * @param userId
	 * @param endTime
	 * @param type
	 */
	@Async("asyncServiceExecutor")
	public void addOrderTask(Long businessId,String orderNo,Long userId,Date endTime,Integer type) {
		OrderTask task = new OrderTask();
		task.setUserId(userId);
		task.setRelatedId(String.valueOf(businessId));
		task.setOrderNo(orderNo);
		task.setType(type);
		task.setEndTime(endTime);
		task.setRemark("订单15分钟开始倒计时");
		orderTaskMapper.insert(task);
	}


	/**
	 * 	修改用户动态记录数 点赞数、评论数、礼物数、分享数、报名数
	 * @param dynamicId		动态ID
	 * @param dynamicType	1=点赞数 2=评论数 3=礼物数 4=分享数 5=报名数
	 * @param type			1=增加 2=减少
	 */
	@Async("asyncServiceExecutor")
	public void updateDynamicRecordCount(Long dynamicId,int dynamicType,int type) {
		UserDynamic dynamic = userDynamicMapper.selectOne(new LambdaQueryWrapper<UserDynamic>().eq(UserDynamic::getId, dynamicId).select(UserDynamic::getId
				,UserDynamic::getLikeCount,UserDynamic::getGiftCount,UserDynamic::getCommentCount,UserDynamic::getShareCount,UserDynamic::getEnrollCount));
		if(null != dynamic) {
			switch (dynamicType) {
			case 1:
				dynamic.setLikeCount(1==type?dynamic.getLikeCount()+1:dynamic.getLikeCount()-1);
				break;
			case 2:
				dynamic.setCommentCount(1==type?dynamic.getCommentCount()+1:dynamic.getCommentCount()-1);
				break;
			case 3:
				dynamic.setGiftCount(1==type?dynamic.getGiftCount()+1:dynamic.getGiftCount()-1);
				break;
			case 4:
				dynamic.setEnrollCount(1==type?dynamic.getEnrollCount()+1:dynamic.getEnrollCount()-1);
				break;
			default:
				break;
			}
			userDynamicMapper.updateById(dynamic);
		}
	}


	/**
	 * 	更新用户经纬度 和 统计用户数量
	 * @param userService
	 * @param city
	 * @param loginUserId
	 * @param longitude
	 * @param latitude
	 * @param request
	 * @param cityCode
	 */
	@Async("asyncServiceExecutor")
	public void update_user_positionn(String city, long loginUserId, BigDecimal longitude,BigDecimal latitude, Integer cityCode,HttpServletRequest request){
		User user = userMapper.selectById(loginUserId);
		if(null == user) {
			return;
		}
		if(StringUtils.isNotEmpty(city)) {
			user.setLoginCityName(city);
		}
		if(null != cityCode) {
			user.setLoginCityCode(cityCode);
		}
		user.setId(loginUserId);
		if(null != longitude) {
			user.setLoginPointX(longitude);
		}
		if(null != latitude) {
			user.setLoginPointY(latitude);
		}

		user.setLoginTime(new Date());
		if(null != request) {
			if(StringUtils.isNotEmpty(request.getHeader("clientType"))) {
				user.setMacAddress(request.getHeader("clientType"));
			}
			if(StringUtils.isNotEmpty(request.getHeader("deviceName"))) {
				user.setDeviceName(request.getHeader("deviceName"));
			}
			if(StringUtils.isNotEmpty(request.getHeader("versionCode"))) {
				user.setClientVersion(String.valueOf(request.getIntHeader("versionCode")));
			}
		}
		//查询VIP是否过期
		if(null == user.getVipExpireTime()) {
			user.setVip(0);
			//VIP已过期 将已经开通的权益消失
			user.setIsStealth(0);
			user.setHideView(0);
//			user.setMessageCount(0);
		}else {
			user.setVip(1);
		}
		userMapper.updateById(user);
	}

	//用户今日是否还可以进行浏览记录推送  true 可以推送
	private static final String viewAndPushToday = "view_and_push_today";
	private boolean viewAndPushToday(Long fromUserId,Long toUserId){
		if(fromUserId==null||toUserId==null){
			return false;
		}
		String value = fromUserId + StrUtil.UNDERLINE + toUserId;
		if(!redisUtil.sHasKey(viewAndPushToday,value)){
			redisUtil.sSetAndTime(viewAndPushToday,DateUtils.getMorningTime()+ RandomUtil.randomInt(5),value);
			return true;
		}
		return false;
	}


	/**
	 * 	增加访问记录
	 * @param userViewRecordMapper
	 * @param loginUserId
	 * @param userId
	 * @param distance
	 * @param userDistance
	 * @param viewedUserDistance
	 * @param hideView
	 */
	@Async("asyncServiceExecutor")
	public void addViewRecord(long loginUserId, long userId, Integer hideView){
		UserViewRecord userView = userViewRecordMapper.selectOne(new LambdaQueryWrapper<UserViewRecord>().eq(UserViewRecord::getUserId, loginUserId)
				.eq(UserViewRecord::getViewedUserId, userId).eq(UserViewRecord::getStatus, hideView));
		if(null == userView) {
			userView = new UserViewRecord();
			userView.setUserId(loginUserId);
			userView.setViewedUserId(userId);
			userView.setStatus(hideView);
			userViewRecordMapper.insert(userView);
		}else {
			userView.setUpdateTime(new Date());
			userView.setEnabled(1);
			userViewRecordMapper.updateById(userView);
		}
		// 消息推送
		if(0 == hideView && viewAndPushToday(loginUserId, userId)) {
			//sendSystemMsg(userId, loginUserId, 1,"","");
		}
	}

	/**
	 * 	修改用户信息
	 * @param user
	 */
	@Async("asyncServiceExecutor")
	public void updateUserInfo(User user){
		userMapper.updateById(user);
		updateUserStatus(user.getId());
	}
	
	/**
	 * 	更新用户忙碌状态
	 * @param userId		发起者ID
	 * @param toUserId		接收者ID
	 * @param isBusy		0=空闲 1=忙碌
	 */
	@Async("asyncServiceExecutor")
	public void updateUserBusy(Long userId,Long toUserId,Integer isBusy) {
		User user = new User();
		user.setId(userId);
		user.setIsBusy(isBusy);
		userMapper.updateById(user);
		User toUser = new User();
		toUser.setId(toUserId);
		toUser.setIsBusy(isBusy);
		userMapper.updateById(toUser);
		updateUserStatus(userId);
		updateUserStatus(toUserId);
	}

	/**
	 * 	注册环信账号
	 * @param userId
	 * @param deviceId
	 */
	@Async("asyncServiceExecutor")
	public void registerEmAccount(String nickName){
		EMUser createUser = eMServiceUtil.createUser(nickName);
		if(null == createUser) {
			return;
		}
	}

	/**
	 * 	环信拉黑
	 * @param userId		当前用户
	 * @param toUserId		对方id
	 * @param type			1=拉黑 2=取消拉黑
	 */
	@Async("asyncServiceExecutor")
	public void blockOrunBlock(Long userId,Long toUserId,Integer type) {
		// 查询用户 环信ID
		UserExtend fromUser = userExtendService.getOne(new QueryWrapper<UserExtend>().eq("user_id", userId).select("em_username"));
		if(null != fromUser) {
			UserExtend toUser = userExtendService.getOne(new QueryWrapper<UserExtend>().eq("user_id", toUserId).select("em_username"));
			if(null != toUser) {
				if(1 == type) {
					eMServiceUtil.blockUser(fromUser.getEmUsername(), toUser.getEmUsername());
					eMServiceUtil.blockUser(toUser.getEmUsername(), fromUser.getEmUsername());
				}else {
					eMServiceUtil.unblockUser(fromUser.getEmUsername(), toUser.getEmUsername());
					eMServiceUtil.unblockUser(toUser.getEmUsername(), fromUser.getEmUsername());
				}
			}
		}
	}

	/**
	 * 	照片打标签 是否真人
	 * @param userId	用户ID
	 * @param fileId	照片ID
	 * @param photoUrl	照片URL
	 */
	@Async("asyncServiceExecutor")
	public void taggingRealPerson(Long userId,Long fileId,String photoUrl){
		// 百度图片比对 QBS 10 
		Semaphore semaphore = new Semaphore(10);
		try {
			// 获取百度token
			String accessToken = "";
			Object object = redisUtil.get("baiduAccessToken");
			if(Objects.isNull(object)) {
				accessToken = AuthService.getAuth();
				redisUtil.set("baiduAccessToken", accessToken,2505600);
			}else {
				accessToken = object.toString();
			}
			// 获取真人认证照片
			FileAttachment realPhoto = fileAttachmentService.getOne(new LambdaQueryWrapper<FileAttachment>().eq(FileAttachment::getUserId, userId)
					.eq(FileAttachment::getFileModule, ProjectConstant.FileModule.REALAUTH).eq(FileAttachment::getEnabled, 1));
			if(null != realPhoto && StringUtils.isNotEmpty(realPhoto.getFilePath()) && StringUtils.isNotEmpty(photoUrl)) {
				semaphore.acquire();
				double compareFaces =  AuthService.compareFaces(accessToken,realPhoto.getFilePath(), photoUrl);
				if(compareFaces >= 65) {
					FileAttachment file = new FileAttachment();
					file.setIsAuth(1);
					file.setId(fileId);
					fileAttachmentService.updateById(file);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			semaphore.release();// 离开
		}
	}

	/**
	 * 	解析认证结果
	 * @param userId		用户ID
	 * @param authImg		认证图片
	 */
	@Async("asyncServiceExecutor")
	public void analysisAuthResult(Long userId,String authImg){
		//将图片存储到OSS
		String path = OSSStsUtil.upload(authImg);
		FileAttachment fileAttachment = fileAttachmentService.getOne(new LambdaQueryWrapper<FileAttachment>()
				.eq(FileAttachment::getUserId, userId).eq(FileAttachment::getFileModule, ProjectConstant.FileModule.REALAUTH).eq(FileAttachment::getEnabled, 1));
		if(null != fileAttachment) {
			fileAttachment.setFilePath(path);
			fileAttachmentService.updateById(fileAttachment);
		}else {
			//修改相册信息-将实名认证相册存入表中
			fileAttachment = new FileAttachment();
			fileAttachment.setUserId(userId);
			fileAttachment.setFileModule(ProjectConstant.FileModule.REALAUTH);
			fileAttachment.setFilePath(path);
			fileAttachmentService.save(fileAttachment);
		}
		// 图片比对 贴标签
		batchTaggingRealPerson(userId);
	}

	/**
	 * 	批量将用户相册贴标签
	 * @param userId
	 */
	@Async("asyncServiceExecutor")
	public void batchTaggingRealPerson(Long userId){
		// 百度图片比对 QBS 10 
		Semaphore semaphore = new Semaphore(10);
		try {
			// 获取百度token
			String accessToken = "";
			Object object = redisUtil.get("baiduAccessToken");
			if(Objects.isNull(object)) {
				accessToken = AuthService.getAuth();
				redisUtil.set("baiduAccessToken", accessToken,2505600);
			}else {
				accessToken = object.toString();
			}
			// 获取真人认证照片
			FileAttachment realPhoto = fileAttachmentService.getOne(new LambdaQueryWrapper<FileAttachment>().eq(FileAttachment::getUserId, userId)
					.eq(FileAttachment::getFileModule, ProjectConstant.FileModule.REALAUTH).eq(FileAttachment::getEnabled, 1));
			if(null != realPhoto && StringUtils.isNotEmpty(realPhoto.getFilePath())) {
				//比对用户相册用户相册  贴上用户认证标签
				List<FileAttachment> updFileList = new ArrayList<FileAttachment>();
				List<FileAttachment> fileList = fileAttachmentService.list(new LambdaQueryWrapper<FileAttachment>().eq(FileAttachment::getUserId, userId)
						.eq(FileAttachment::getFileModule, ProjectConstant.FileModule.REALAUTH).eq(FileAttachment::getEnabled, 1));
				semaphore.acquire();
				for (FileAttachment file : fileList) {
					if(StringUtils.isNotEmpty(file.getFilePath())) {
						semaphore.acquire();
						double compareFaces =  AuthService.compareFaces(accessToken,realPhoto.getFilePath(), file.getFilePath()) ;
						if(compareFaces >= 65) {
							file.setIsAuth(1);
							updFileList.add(file);
						}
					}
				}
				//贴标签
				if(CollectionUtils.isNotEmpty(updFileList)) {
					fileAttachmentService.updateBatchById(updFileList);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			semaphore.release();// 离开
		}
	}


	/**
	 * 	推送系统消息
	 * @param userId		接收的用户ID
	 * @param toUserId		点击跳转到用户主页的ID
	 * @param type			1=解锁聊天 2=接收礼物
	 * 
	 * @param extend1,extend2 	扩展字段 根据业务传入对应的值
	 */
	@Async("asyncServiceExecutor")
	public void sendSystemMsg(Long userId, Long toUserId,Integer type,String extend1,String extend2) {
		try {
			AppUserDetail userDetail = new AppUserDetail();
			userDetail.setType(1);
			userDetail.setUserId(userId);
			List<AppUserDetail> userDetailList = new ArrayList<AppUserDetail>();
			// 个推需要的设备号和分组名
			List<String> deviceList = new ArrayList<String>();
			String groupName = "";
			String title = "";
			String content = "";
			String icon = "";
			Integer msgType = 1;// 1=系统消息 2=订单消息
			// 推送的用户ID集合
			List<String> list = new ArrayList<String>();
			UserSystemMsg msgEntity = null;
			switch (type) {
			case 1:	// 解锁微信消息
				userDetailList = userMapper.getUserBasicInfo(userDetail);
				if(CollectionUtils.isNotEmpty(userDetailList)) {
					userDetail = userDetailList.get(0);
					title = "解锁微信";
					content = "用户”"+userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, toUserId).select(User::getId,User::getNickName)).getNickName()+"“解锁了你的微信,快去打招呼吧~";
					icon = SystemPushText.BDAppPushIcon.SYSTEM_ICON;
					list.add(userDetail.getEmUsername());
					if(StringUtils.isNotEmpty(userDetail.getDeviceId())) {
						deviceList.add(userDetail.getDeviceId());
					}
				}
				break;
			case 2:	// 收到礼物消息
				userDetailList = userMapper.getUserBasicInfo(userDetail);
				if(CollectionUtils.isNotEmpty(userDetailList)) {
					userDetail = userDetailList.get(0);
					title = "赠送礼物";
					content = "用户”"+userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, toUserId).select(User::getId,User::getNickName)).getNickName()+"“给你赠送了礼物,快去打招呼吧~";
					icon = SystemPushText.BDAppPushIcon.SYSTEM_ICON;
					list.add(userDetail.getEmUsername());
					if(StringUtils.isNotEmpty(userDetail.getDeviceId())) {
						deviceList.add(userDetail.getDeviceId());
					}
				}
				break;
			default:
				break;
			}
			// 消息推送
			if(CollectionUtils.isNotEmpty(list)) {
				Map<String,Object> map = new HashMap<String, Object>();
				map.put("type", type);
				// 环信和数据存入
				emBatchPushAndSave(list, userDetailList,userId, toUserId, title, content, icon,map,msgType,msgEntity);
				// 个推
				if(CollectionUtils.isNotEmpty(deviceList)) {
					sendUnipush(title, content, groupName, deviceList);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 	聊天 个推推送
	 * @param content
	 * @param userId
	 */
	@Async("asyncServiceExecutor")
	public void pushChatMsg(String content,Long userId) {
		AppUserDetail userDetail = new AppUserDetail();
		userDetail.setType(1);
		userDetail.setUserId(userId);
		List<AppUserDetail> userDetailList = userMapper.getUserBasicInfo(userDetail);
		if(CollectionUtil.isNotEmpty(userDetailList)) {
			if(StringUtils.isNotEmpty(userDetailList.get(0).getDeviceId())) {
				List<String> deviceList = new ArrayList<String>();
				deviceList.add(userDetailList.get(0).getDeviceId());
				sendUnipush(content, content, content, deviceList);
			}
		}
	}
	
	// 个推推送
	private void sendUnipush(String title,String content,String groupName,List<String> deviceList) {
		if(deviceList.size() > 1) {
			// 批量
			String taskId = UniBatchPushUtil.createMsg(title, content, groupName);
			if(StringUtils.isNotEmpty(taskId)) {
				if(deviceList.size() > 1000) {
					int limit = (deviceList.size() -1) / 10;
					for (int i = 0; i <=limit; i++) {
						int fromIndex = i * 10;
						int toIndex = (i + 1) * 10;
						if (i == limit){
							toIndex = deviceList.size();
						}
						List<String> cids = deviceList.subList(fromIndex, toIndex).stream().collect(Collectors.toList());
						UniBatchPushUtil.pushListByCid(taskId, cids);
					}
				}else {
					UniBatchPushUtil.pushListByCid(taskId, deviceList);
				}
			}
		}else {
			// 单推
			UnipushUtil.pushMsg(title, content, deviceList.get(0));
		}
	}

	// 批量EM推送 且添加到数据库
	private void emBatchPushAndSave(List<String> list,List<AppUserDetail> userDetailList,Long userId,Long toUserId,String title,String content,String icon,Map<String,Object> map,Integer type,UserSystemMsg msgEntity) {
		if(list.size() > 600) {
			int limit = (list.size() -1) / 10;
			for (int i = 0; i <=limit; i++) {
				int fromIndex = i * 10;
				int toIndex = (i + 1) * 10;
				if (i == limit){
					toIndex = list.size();
				}
				Set<String> setIds = list.subList(fromIndex, toIndex).stream().collect(Collectors.toSet());
				eMServiceUtil.sendSystemMsg(title, setIds,map);
			}
		}else {
			Set<String> setIds = list.stream().collect(Collectors.toSet());
			eMServiceUtil.sendSystemMsg(title, setIds,map);
			System.out.println("消息推送完成");
		}
		// 存入数据库
		if(CollectionUtils.isNotEmpty(userDetailList)) {
			List<UserSystemMsg> pushList = new ArrayList<UserSystemMsg>();
			userDetailList.parallelStream().forEach(user ->{
				UserSystemMsg userMsg = new UserSystemMsg();
				userMsg.setUserId(userId);
				userMsg.setToUserId(toUserId);
				userMsg.setTitle(title);
				userMsg.setContent(content);
				userMsg.setIcon(icon);
				userMsg.setType(1);
				pushList.add(userMsg);
			});
			userSystemMsgService.saveBatch(pushList);
		}
	}
}
